package edu.olin.scheduler.gui.schedule;

import edu.olin.scheduler.common.*;
import edu.olin.scheduler.gui.*;
import edu.olin.scheduler.gui.layout.*;
import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class SingleDayDisplay extends JPanel implements GUIPrefs.Listener {

    private int dayOfWeek;
    private JLabel dayLabel;
    
    private ArrayList<MeetingDisplay> meetingDisplays;
    private ArrayList<DisplayGroup> displayGroups;
    
    public static final String[] days = { "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
    
    public SingleDayDisplay(int dayOfWeek){
        super(true);
        if(dayOfWeek<0 || dayOfWeek>6){ throw new IllegalArgumentException("Invalid day of week; 0<=dayOfWeek<=6"); }
        this.dayOfWeek = dayOfWeek;
        GUIPrefs.addListener(this);
        meetingDisplays = new ArrayList();
        displayGroups = new ArrayList();
        dayLabel = new JLabel(days[dayOfWeek],JLabel.CENTER);
            dayLabel.setOpaque(true);
            dayLabel.setBackground(GUIPrefs.getMarginBGColor());
            dayLabel.setForeground(GUIPrefs.getMarginFGColor());
            dayLabel.setFont(GUIPrefs.getDayOfWeekFont());
            add(dayLabel);
        setBackground(GUIPrefs.getDailyBGColor());
        setLayout(null);
        setOpaque(true);
        }
    
    public void guiPrefsChanged(){
        setBackground(GUIPrefs.getDailyBGColor());
        dayLabel.setFont(GUIPrefs.getDayOfWeekFont());
        
        doLayout();
        repaint();
        }
    
    public void clear(){
        Iterator<MeetingDisplay> itr = meetingDisplays.iterator();
        while(itr.hasNext()){ remove(itr.next()); }
        meetingDisplays.clear(); //toss everything
        displayGroups.clear();
        rebuildDisplayGroups(); //re-consider this element in our layout
        doLayout(); //re-layout the components
        }
    
    public void addMeetingDisplay(MeetingDisplay md){
        if(md==null){ throw new IllegalArgumentException("Cannot add a null meeting"); }
        meetingDisplays.add(md); //add the element to the list
        this.add(md); //add the GUI element to this panel
        rebuildDisplayGroups(); //re-consider this element in our layout
        doLayout(); //re-layout the components
        }
    
    public void paint(Graphics g){
        super.paint(g);
        //draw major/minor lines
        LineDrawer.drawLines(g,GUIPrefs.getMarginSize()+5,getWidth()-5,GUIPrefs.getHeaderSize(),getHeight());
        //draw left-margin bar
        g.setColor(GUIPrefs.getMarginFGColor());
        g.fillRect(0,0,GUIPrefs.getMarginSize(),getHeight());
        //draw in the day label
        dayLabel.setLocation(GUIPrefs.getMarginSize(),0);
        dayLabel.setSize(getWidth(),GUIPrefs.getHeaderSize());
        //draw all of the subcomponents
        paintComponents(g);
        g.setColor(GUIPrefs.getMarginBGColor());
        g.drawLine(GUIPrefs.getMarginSize(),GUIPrefs.getHeaderSize(),getWidth(),GUIPrefs.getHeaderSize());
        }
    
    public void rebuildDisplayGroups(){
        MeetingDisplay[] sortedMeetingDisplays = meetingDisplays.toArray(new MeetingDisplay[]{});
        Arrays.sort(sortedMeetingDisplays); //get our meetingDisplays sorted
        ArrayList<DisplayGroup> groups = new ArrayList();
        DisplayGroup g = null;
        for(int i=0; i<sortedMeetingDisplays.length; i++){
            MeetingDisplay md = sortedMeetingDisplays[i];
            if( g==null || !md.getMeeting().start().isBefore(g.end()) ){
                g = new DisplayGroup();
                groups.add(g);
                }
            g.add(md);
            }
        displayGroups = groups; //save new groups
        }
    
    //at what y-position on this SingleDayDisplay is the given SimpleTime?
    private int getYPosition(SimpleTime st){
        return LineDrawer.getYPosition(st,dayLabel.getHeight(),getHeight());
        }
    
    public void doLayout(){
        Iterator<DisplayGroup> itr = displayGroups.iterator();
        int margin = GUIPrefs.getMarginSize();
        int width = getWidth() - margin - 1;
        while(itr.hasNext()){
            DisplayGroup g = itr.next();
            Color bgColor = (g.numCols()>1) ? GUIPrefs.getMtbgColorConflict() : GUIPrefs.getMtbgColor();
            for(int col=0; col<g.numCols(); col++){
                MeetingDisplay[] displays = g.getColumn(col);
                for(int i=0; i<displays.length; i++){
                    MeetingDisplay md = displays[i];
                    int y = getYPosition(md.getMeeting().start());
                    int x = (width*col)/g.numCols();
                    int w = (width*(col+1))/g.numCols() - x + 1;
                    int h = getYPosition(md.getMeeting().end()) - y + 1;
                    md.setBackground(bgColor);
                    md.setExtendsBack(md.getMeeting().start().isBefore(GUIPrefs.getStart()));
                    md.setExtendsForwards(md.getMeeting().end().isAfter(GUIPrefs.getEnd()));
                    md.setSize(w,h);
                    md.setLocation(x+margin-1,y);
                    }
                }
            }
        repaint();
        }
    
    }
